package cool.taomu.toolkit.service.kademlia.utils

import cool.taomu.toolkit.crypto.Base64
import cool.taomu.toolkit.service.kademlia.utils.BEncodeUtils
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileInputStream
import java.security.MessageDigest
import java.util.ArrayList
import java.util.HashMap
import java.util.List
import org.slf4j.LoggerFactory

class TorrentUtils {
	val static LOG = LoggerFactory.getLogger(TorrentUtils);

	def static void create(File file, long pieceLength) {
		if (file.exists) {
			// var long pieceLength = 262144L;
			var pieceHashes = generatePieceHashes(file, pieceLength)

			val ByteArrayOutputStream piecesStream = new ByteArrayOutputStream();
			pieceHashes.forEach [ hash |
				piecesStream.write(hash);
			]

			var byte[] piecesBinary = piecesStream.toByteArray();
			LOG.info("Total pieces: " + pieceHashes.size());
			LOG.info("Pieces length: " + piecesBinary.length);
			LOG.info("Valid: " + (piecesBinary.length % 20 == 0));

			var torrentFile = #[file.absolutePath, "torrent"].join(".")
			var dict = new HashMap<String, Object>()
            dict.put("creation date", System.currentTimeMillis / 1000)
			dict.put("comment", "节点信息")
			dict.put("info", #{
				"length" -> file.length,
				"name" -> file.name,
				"piece length" -> pieceLength,
				"pieces" -> new Base64(piecesBinary).encode
			});
			BEncodeUtils.write(dict, torrentFile)
		}
	}

	def static List<byte[]> generatePieceHashes(File file, long pieceLength) throws Exception {
		var List<byte[]> hashes = new ArrayList<byte[]>();
		var MessageDigest sha1 = MessageDigest.getInstance("SHA-1");

		try (var FileInputStream fis = new FileInputStream(file)) {
			var byte[] buffer = newByteArrayOfSize(Math.min(pieceLength, 8 * 1024 * 1024) as int); // 最多缓存 8MB
			var int bytesRead;

			while ((bytesRead = fis.read(buffer)) > 0) {
				// 如果当前读取的数据小于 pieceLength，说明是最后一块
				var boolean isLastPiece = bytesRead < pieceLength;

				// 创建一个精确大小的数组保存当前 piece 数据
				var byte[] pieceData = newByteArrayOfSize(bytesRead);
				System.arraycopy(buffer, 0, pieceData, 0, bytesRead);

				// 计算哈希
				var byte[] hash = sha1.digest(pieceData);
				hashes.add(hash);

				// 如果不是最后一块，则重置 digest 缓冲区以便下次计算
				if (!isLastPiece) {
					sha1.reset();
				}
			}
		}

		return hashes;
	}
}
